// eee.Sheffield.PZ.Imaging
//
// Copyright ?Ping Zou, 2006
// sg71.cherub@gmail.com
using System;
using System.Collections.Generic;
using System.Text;
using eee.Sheffield.PZ.Math;
using System.Drawing;
using System.Drawing.Imaging;
namespace eee.Sheffield.PZ.Imaging.ImageFilter
{
    public class GaussianY : DoubleKernel1D // ImageFilter//, IGraylevelImageFilter
    {
        #region Fields
        /// <summary>
        /// standard deviation of the distribution
        /// </summary>
        private double _sigma;       
        /// <summary>
        /// convolution kernel
        /// </summary>
        //private double[] _kernel;
        /// <summary>
        /// kernel size (3 * mSigma)
        /// </summary>
        private int _lernelSize;
        /// <summary>
        /// kernel length (2 * mKernelSize + 1)
        /// </summary>
        private int _kernelLength;
        //private string _flag = "[Image -> Smooth -> GaussianY]";
        #endregion

        #region Properties
        //public string Flag() { return _flag; } 
        //public string Log() { return _log; }
        public double Sigma{get { return _sigma; }set { _sigma = value; }}
        //public int KernelSize{get { return _lernelSize; }set { _lernelSize = value; }}
        #endregion

        #region constructor
        /// <summary>
        /// empty constructor
        /// </summary>
        public GaussianY() : this(0) { }
        /// <summary>
        /// imput standard deviation of the distribution
        /// </summary>
        /// <param name="sigma"></param>
        public GaussianY(double sigma)
        {
            _flag = "[Image -> Smooth -> GaussianY]";
            _sigma = sigma;
            _isXDirection = false;
            PrepareKernel();
        }
        #endregion

        #region prepare kernel
        private void PrepareKernel()
        {
            if (_sigma == 0)
                PZMath_errno.ERROR("GaussianY::PrepareKernel(), sigma is not prepared");
            _lernelSize = Convert.ToInt32(System.Math.Ceiling(3 * _sigma));
            _kernelLength = 2 * _lernelSize + 1;
            _kernel = new double[_kernelLength];
            // calculate kernel element
            double term1 = 1 / System.Math.Sqrt(2 * System.Math.PI) / _sigma / _sigma;
            for (int i = 0; i <= _lernelSize; i++)
            {
                double element = term1 * System.Math.Exp(-1.0 * (double)i * (double)i / 2.0 / _sigma / _sigma);
                _kernel[_lernelSize + i] = element;
                _kernel[_lernelSize - i] = element;
            }
        }
        #endregion

        #region Apply filter
        //public Bitmap ApplyGraylevelImageFilter(Bitmap srcImage) { return Apply(srcImage, out _log); }
        //public PZMath_matrix ApplyDoubleGraylevelImageFilter(PZMath_matrix srcMatrix) { return ApplyDouble(srcMatrix, out _log); }

        //private Bitmap Apply(Bitmap srcImage, out string logText)
        //{
        //    PZMath_matrix srcMatrix = _converter.ConvertGraylevelBitmapToMatrix(srcImage);
        //    PZMath_matrix dstMatrix = ApplyDouble(srcMatrix, out logText);
        //    Bitmap dstImage = _converter.ConvertMatrixToGraylevelBitmap(dstMatrix);
        //    return dstImage;
        //}     

        //protected override PZMath_matrix ApplyDoubleGraylevelImageFilter(PZMath_matrix srcMatrix, out string logText)
        //{
        //    #region source and dst matrix
        //    // get source
        //    int width = srcMatrix.ColumnCount;
        //    int height = srcMatrix.RowCount;

        //    // create dstMatrix
        //    PZMath_matrix dstMatrix = new PZMath_matrix(height, width);
        //    int heightM1 = height - 1;
        //    int widthM1 = width - 1;
        //    int heightM2 = height - 2;
        //    int widthM2 = width - 2;
        //    #endregion

        //    #region Gaussian filter, Y direction
        //    // for each pixel
        //    for (int y = 0; y < height; y++)
        //    {
        //        for (int x = 0; x < width; x++)
        //        {
        //            // copy "margin" part
        //            if (y < _lernelSize || y >= height - _lernelSize)
        //            {
        //                dstMatrix[y, x] = srcMatrix[y, x];
        //            }
        //            else
        //            // do kernel convolution, Y-direction
        //            {
        //                // inside kernel
        //                double intensity = 0.0;
        //                for (int kernelIndex = 0; kernelIndex < _kernelLength; kernelIndex++)
        //                {
        //                    intensity += srcMatrix[y + kernelIndex - _lernelSize, x] * _kernel[kernelIndex];
        //                }
        //                dstMatrix[y, x] = intensity;
        //            }
        //        }
        //    }
        //    #endregion
        //    logText = "succeeds.";
        //    return dstMatrix;
        //}

        ///// <summary>
        ///// apply filter, Y direction, return double matrix
        ///// </summary>
        ///// <param name="srcMatrix"></param>
        ///// <returns></returns>
        //protected override PZMath_matrix[] ApplyDoubleColourImageFilter(PZMath_matrix[] srcMatrixArray, out string logText)
        //{
        //    // TODO: verify this function

        //    #region Source and Dest Matrix
        //    // get source
        //    PZMath_matrix srcR = srcMatrixArray[0];
        //    PZMath_matrix srcG = srcMatrixArray[1];
        //    PZMath_matrix srcB = srcMatrixArray[2];

        //    int width = srcR.ColumnCount;
        //    int height = srcR.RowCount;

        //    // create dstMatrix
        //    PZMath_matrix[] dstMatrix = new PZMath_matrix[3];
        //    dstMatrix[0] = new PZMath_matrix(height, width);
        //    dstMatrix[1] = new PZMath_matrix(height, width);
        //    dstMatrix[2] = new PZMath_matrix(height, width);
        //    PZMath_matrix dstR = dstMatrix[0];
        //    PZMath_matrix dstG = dstMatrix[1];
        //    PZMath_matrix dstB = dstMatrix[2];
        //    #endregion

        //    #region Gaussian filter, Y direction
        //    // for each pixel
        //    for (int y = 0; y < height; y++)
        //    {
        //        for (int x = 0; x < width; x++)
        //        {
        //            // copy "margin" part
        //            if (y < _lernelSize || y >= height - _lernelSize)
        //            {
        //                dstR[y, x] = srcR[y, x];
        //                dstG[y, x] = srcG[y, x];
        //                dstB[y, x] = srcB[y, x];
        //            }
        //            else
        //            // do kernel convolution, Y-direction
        //            {
        //                // inside kernel
        //                double intensityR = 0.0;
        //                double intensityG = 0.0;
        //                double intensityB = 0.0;
        //                for (int kernelIndex = 0; kernelIndex < _kernelLength; kernelIndex++)
        //                {
        //                    intensityR += srcR[y + kernelIndex - _lernelSize, x] * _kernel[kernelIndex];
        //                    intensityG += srcG[y + kernelIndex - _lernelSize, x] * _kernel[kernelIndex];
        //                    intensityB += srcB[y + kernelIndex - _lernelSize, x] * _kernel[kernelIndex];
        //                }
        //                dstR[y, x] = intensityR;
        //                dstG[y, x] = intensityG;
        //                dstB[y, x] = intensityB;
        //            }
        //        }
        //    }
        //    #endregion
        //    logText = "succeeds.";
        //    return dstMatrix;
        //}
        #endregion        
    }
}
